透過 day19 的內容,我們可以根據事先定義好的形式來抓取要特定資料,那麼今天就做的小專案,透過正則表達式來抓取我們在鐵人30天的標題。
首先這是我們 鐵人30天的網址,可能之後會隨著文章的新增而與後面的結果不同,因此會附上一個目前我在爬蟲時的網路源碼,會附在 代碼連結中,簡易爬蟲的流程如下:
首先我們的目標網站畫面如下:
透過右鍵點擊檢查原始碼:
原始碼畫面如下:
目標:
看到標題出現時的規律前都會有下面這一行,我們就可以利用這個來定義正則表達式
class="qa-list__title-link"
以下附上程式碼,並且裡面有當時測試的源碼檔案,名為 itTitle.html
const url = "https://ithelp.ithome.com.tw/users/20150797/ironman/5271?page=2"
// 從網路上讀取資料
func Fetcher(url string) ([]byte, error) {
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, fmt.Errorf("new request error %s", err)
}
// 有些 url 需要有 User-Agent 的資訊,否則會出現 403 的問題,鐵人30 就需要這個東西
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("client error %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("wrong status code: %d", resp.StatusCode)
}
return ioutil.ReadAll(resp.Body)
}
// 從檔案讀取資料
func ReadFile(fileName string) ([]byte, error) {
file, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, fmt.Errorf("read file error: %s", err)
}
return file, err
}
// 正則表達式
var HotQuestionRe = `class=\"qa-list__title-link\">\s*([^<]*)`
// 檔案路徑
var filePath = "day20/itTitle.html"
func main() {
// 從網路獲取文章
html, err := Fetcher(url)
// 從文檔讀取文章
// html, err := ReadFile(filePath)
if err != nil {
fmt.Println(err)
}
//解析正则表達式,如果成功返回解释器
reg := regexp.MustCompile(HotQuestionRe) // \t表空格,[^\t]表示除了空格外,其他都可
if reg == nil {
fmt.Println("regexp err")
return
}
// 文章匹配正則表達式
result := reg.FindAllSubmatch(html, -1)
var s []string
for _, v := range result {
trimV := strings.TrimSpace(string(v[1]))
s = append(s, trimV)
}
// 輸出結果
for i := range s {
fmt.Println(s[i])
}
}
輸出結果為:
Day11 - Go的文檔制作
Day12 - Go的 goroutine
Day13 - Go的 channel (上)
Day14 - Go的 channel (下)
Day15 - Go的 WaitGroup
Day16 - Go的 Mutex (互斥鎖)
Day17 - Go的 Select
Day18 - Go的 package
Day19 - Go的正則表達式
https://github.com/luckyuho/ithome30-golang/tree/main/day20